﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using MvcEngine.Core.Utils;
using MvcEngine.Mvc.View.Skin;

namespace MvcEngine.Mvc.View.ViewEngine
{
    public class CustomViewEngine : IViewEngine
    {
        #region Public properties
        public ISkinEngine SkinEngine { get; private set; } 
        #endregion

        #region Constructors

        public CustomViewEngine(ISkinEngine skinEngine)
        {
            SkinEngine = skinEngine;
        } 

        #endregion

        #region Protected methods

        protected virtual IView CreatePartialView(ControllerContext controllerContext, string partialPath)
        {
            return new MvcEngineWebFormView(partialPath) { SkinEngine = SkinEngine };
        }

        protected virtual IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
        {
            return new MvcEngineWebFormView(viewPath, masterPath) { SkinEngine = SkinEngine };
        } 

        #endregion

        #region Public methods

        public virtual ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }

            if (string.IsNullOrEmpty(partialViewName))
            {
                throw new ArgumentNullException("partialViewName");
            }

            string controllerName = controllerContext.RouteData.GetRequiredString("controller");
            

#warning change this make it testable
            //string moduleName = System.Web.HttpContext.Current.Items["CurrentModule"] as string; //ModuleManager.Current.GetModuleName(viewContext.Controller.ControllerContext.Controller.GetType().Assembly.GetName().Name);
            string moduleName = controllerContext.RouteData.Values["moduleName"] as string;

            string[] locationsSearched;
            string partialPath = SkinEngine.FindPartialViewPath(partialViewName, controllerContext.RouteData.DataTokens["area"].ToString(), controllerName, moduleName, out locationsSearched);

            return !string.IsNullOrEmpty(partialPath)
                       ? new ViewEngineResult(CreatePartialView(controllerContext, partialPath), this)
                       : new ViewEngineResult(locationsSearched);
        }

        public virtual ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }

            if (string.IsNullOrEmpty(viewName))
            {
                throw new ArgumentNullException("viewName");
            }

            string controllerName = controllerContext.RouteData.GetRequiredString("controller");

#warning change this make it testable
            //string moduleName = System.Web.HttpContext.Current.Items["CurrentModule"] as string; //ModuleManager.Current.GetModuleName(viewContext.Controller.ControllerContext.Controller.GetType().Assembly.GetName().Name);
            string moduleName = controllerContext.RouteData.Values["moduleName"] as string;

            var areaName = controllerContext.RouteData.DataTokens["area"].ToString();

            string[] viewLocationsSearched;
            string viewPath = SkinEngine.FindViewPath(viewName, areaName, controllerName, moduleName, out viewLocationsSearched);

            if (string.IsNullOrEmpty(viewPath))
            {
                return new ViewEngineResult(viewLocationsSearched);
            }

            string[] masterLocationsSearched;
            string masterPath = SkinEngine.FindMasterPath(masterName, areaName, controllerName, moduleName, out masterLocationsSearched);

            if (!string.IsNullOrEmpty(masterName) && string.IsNullOrEmpty(masterPath))
            {
                return new ViewEngineResult(masterLocationsSearched);
            }

            return new ViewEngineResult(CreateView(controllerContext, viewPath, masterPath), this);
        }

        public void ReleaseView(ControllerContext controllerContext, IView view)
        {
            IDisposable disposable = view as IDisposable;
            if (disposable != null)
            {
                disposable.Dispose();
            }
        } 

        #endregion
    }
}
